package com.baomidou.kisso.service;

import cn.hutool.extra.spring.SpringUtil;
import com.aizuda.boot.modules.third.wps.enums.WebOfficeHeader;
import com.aizuda.common.toolkit.ThreadLocalUtils;
import com.baomidou.kisso.SSOCache;
import com.baomidou.kisso.SSOConfig;
import com.baomidou.kisso.SSOPlugin;
import com.baomidou.kisso.common.Browser;
import com.baomidou.kisso.common.CookieHelper;
import com.baomidou.kisso.common.IpHelper;
import com.baomidou.kisso.common.SSOConstants;
import com.baomidou.kisso.common.util.StringUtils;
import com.baomidou.kisso.enums.TokenFlag;
import com.baomidou.kisso.exception.KissoException;
import com.baomidou.kisso.security.token.SSOToken;
import com.baomidou.kisso.security.token.Token;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;

import java.util.Iterator;
import java.util.List;
import java.util.Objects;

/**
 * @author hjw
 * @description
 * @date 2025年06月25日 16:32
 */
@Slf4j
public class KissoServiceSupport {

    public static final String KISSO_TOKEN = "eyJhbGciOiJIUzUxMiJ9.eyJqdGkiOiIxOTM3NDUzNTM1MzIxMTk4NTk0IiwidGlkIjoiMTBiODdiN2YxODk3NTc1ZiIsImlzcyI6ImhvdWppYXdlaUZzIiwidWEiOiJiYTQ5MiIsIm9nIjoiMSIsImlhdCI6MCwic2lkIjoiMTJkYWRiYmI5ZGIzNzk3MGI4ZWU4ZmI2OGQ2NWU5ZDAifQ.OvH3qBgwSOmvYduztLPUBzZB4zPZ5gFY8-wYEsdAyZzZ2aK3iJUGZcYtdcYNdEBEYW804SaLL7HSXEd19Vzb9A";


    protected SSOConfig config;

    public KissoServiceSupport() {
    }

    public <T extends SSOToken> T attrSSOToken(HttpServletRequest request) {
        SSOToken kissoTokenAttr = (SSOToken) request.getAttribute("kissoTokenAttr");
        return (T) kissoTokenAttr;
    }

    protected SSOToken cacheSSOToken(HttpServletRequest request, SSOCache cache) {
        if (cache != null) {
            SSOToken cookieSSOToken = this.getSSOTokenFromCookie(request);
            if (cookieSSOToken == null) {
                return null;
            }

            SSOToken cacheSSOToken = cache.get(cookieSSOToken.toCacheKey(), this.config.getCacheExpires());
            if (cacheSSOToken == null) {
                log.debug("cacheSSOToken SSOToken is null.");
                return null;
            }

            if (cacheSSOToken.getFlag() != TokenFlag.CACHE_SHUT) {
                if (cookieSSOToken.getTime() / SSOConstants.JWT_TIMESTAMP_CUT == cacheSSOToken.getTime() / SSOConstants.JWT_TIMESTAMP_CUT) {
                    return cacheSSOToken;
                }

                log.debug("Login time is not consistent or kicked out.");
                request.setAttribute("kissoKickFlag", "kissoKickUser");
                return null;
            }
        }

        return this.getSSOToken(request, this.config.getCookieName());
    }

    protected SSOToken getSSOToken(HttpServletRequest request, String cookieName) {
        String accessToken = request.getHeader(this.config.getAccessTokenName());
        //兼容WPS请求头
        if (StringUtils.isEmpty(accessToken)) {
            accessToken = request.getHeader(WebOfficeHeader.X_WEB_OFFICE_TOKEN);
            log.debug("从WPS请求头获取Token: " + accessToken);
            //    dev环境下设置默认Token
            String profile = SpringUtil.getActiveProfile();
            if (StringUtils.isEmpty(accessToken) && "dev".equals(profile)) {
                accessToken = KISSO_TOKEN;
            }
            if (ThreadLocalUtils.get(this.config.getAccessTokenName()) != null) {
                accessToken = ThreadLocalUtils.get(this.config.getAccessTokenName());
            }
        }

        if (StringUtils.isEmpty(accessToken)) {
            Cookie uid = CookieHelper.findCookieByName(request, cookieName);
            if (null == uid) {
                log.debug("Unauthorized login request, ip=" + IpHelper.getIpAddr(request));
                return null;
            } else {
                return SSOToken.parser(uid.getValue(), false);
            }
        } else {
            return SSOToken.parser(accessToken, true);
        }
    }

    protected SSOToken checkIpBrowser(HttpServletRequest request, SSOToken ssoToken) {
        if (null == ssoToken) {
            return null;
        } else if (this.config.isCheckBrowser() && !Browser.isLegalUserAgent(request, ssoToken.getUserAgent())) {
            log.info("The request browser is inconsistent.");
            return null;
        } else {
            if (this.config.isCheckIp()) {
                String ip = IpHelper.getIpAddr(request);
                if (ip != null && !ip.equals(ssoToken.getIp())) {
                    log.info(String.format("ip inconsistent! return SSOToken null, SSOToken userIp:%s, reqIp:%s", ssoToken.getIp(), ip));
                    return null;
                }
            }

            return ssoToken;
        }
    }

    public SSOToken getSSOTokenFromCookie(HttpServletRequest request) {
        SSOToken tk = this.attrSSOToken(request);
        if (tk == null) {
            tk = this.getSSOToken(request, this.config.getCookieName());
        }

        return tk;
    }

    protected SSOCookie generateCookie(HttpServletRequest request, Token token) {
        try {
            SSOCookie ssoCookie = new SSOCookie(this.config.getCookieName(), token.getToken());
            ssoCookie.setPath(this.config.getCookiePath());
            ssoCookie.setSecure(Objects.equals(request.getScheme(), "https"));
            ssoCookie.setHttpOnly(this.config.isCookieHttpOnly());
            ssoCookie.setSameSite(this.config.getCookieSameSite());
            String domain = this.config.getCookieDomain();
            if (null != domain) {
                ssoCookie.setDomain(domain);
                if ("".equals(domain) || domain.contains("localhost")) {
                    log.warn("if you can't login, please enter normal domain. instead:" + domain);
                }
            }

            int maxAge = this.config.getCookieMaxAge();
            Integer attrMaxAge = (Integer) request.getAttribute("kisso_cookie_maxage");
            if (attrMaxAge != null) {
                maxAge = attrMaxAge;
            }

            if (maxAge >= 0) {
                ssoCookie.setMaxAge(maxAge);
            }

            return ssoCookie;
        } catch (Exception var7) {
            Exception e = var7;
            throw new KissoException("Generate sso cookie exception ", e);
        }
    }

    protected boolean logout(HttpServletRequest request, HttpServletResponse response, SSOCache cache) {
        if (cache != null && !"kissoKickUser".equals(request.getAttribute("kissoKickFlag"))) {
            SSOToken tk = this.getSSOTokenFromCookie(request);
            if (tk != null) {
                boolean rlt = cache.delete(tk.toCacheKey());
                if (!rlt) {
                    cache.delete(tk.toCacheKey());
                }
            }
        }

        List<SSOPlugin> pluginList = this.config.getPluginList();
        if (pluginList != null) {
            Iterator var9 = pluginList.iterator();

            while (var9.hasNext()) {
                SSOPlugin plugin = (SSOPlugin) var9.next();
                boolean logout = plugin.logout(request, response);
                if (!logout) {
                    plugin.logout(request, response);
                }
            }
        }

        return CookieHelper.clearCookieByName(request, response, this.config.getCookieName(), this.config.getCookieDomain(), this.config.getCookiePath());
    }
}
